-module(vnode).

-compile(export_all).

-include("scatter_region.hrl").

-include_lib("eunit/include/eunit.hrl").

main() ->
    RS = #region_state{
        id = now(),
        topological_region = #topological_region{
            region = #region{left=0,top=1024,right=1024,bottom=0}
        }
    },
    spawn(?MODULE, vc_server, [RS]),
    ok.

vc_server(State) ->
    {_,_,I2} = State#region_state.id,
    Id = list_to_atom("v_" ++ erlang:integer_to_list(I2)),
    io:format("server: ~p~n", [Id]),
    register(Id, self()),
    vc_loop(State#region_state{self=self()}).

vc_loop(State) ->
    receive
        {adjust_outlet, OutletRange} ->
            TR = State#region_state.topological_region,
            case matrix2:adjust_outlet(TR, OutletRange) of
                {continue, NewTopoRegion} ->
                    State#region_state.pred ! {adjust_outlet, NewTopoRegion#topological_region.interface};
                {stop_here, NewTopoRegion} ->
                    ok
            end,
            vc_loop(State#region_state{topological_region=NewTopoRegion});
        {adjust_inlet, InletRange} ->
            TR = State#region_state.topological_region,
            case matrix2:adjust_inlet(TR, InletRange) of
                {continue, NewTopoRegion} ->
                    State#region_state.succ ! {adjust_inlet, NewTopoRegion#topological_region.outerface};
                {stop_here, NewTopoRegion} ->
                    ok
            end,
            vc_loop(State#region_state{topological_region=NewTopoRegion});
        bisection ->
            NewState = divide(State),
            vc_loop(NewState);
        {traverse, Flag} ->
            NewState = traverse(State, Flag),
            vc_loop(NewState)
    end.


divide(#region_state{pred=undefined, succ=undefined} = State) ->
%    R1 = #region{left=L,top=T,right=L+(R-L)/2,bottom=B},
%    R2 = #region{left=L+(R-L)/2,top=T,right=R,bottom=B},
    {R1, R2} = matrix2:divide(State#region_state.topological_region),
    S2 = #region_state{
        id = now(),
        pred = self(), succ = self(),
        topological_region = R2
    },
    Pid2 = spawn(?MODULE, vc_server, [S2]),
    State#region_state{
        pred = Pid2, succ = Pid2,
        topological_region = R1
    };
divide(State) ->
    {PredRegion, SuccRegion} = matrix2:divide(State#region_state.topological_region),
%    PR = PredRegion#topological_region.region,
%    SR = SuccRegion#topological_region.region,
%    if 
%        ((PR#region.top =< SR#region.right) and (PR#region.right =< SR#region.right)) ->
%            {R2, R1} = {PredRegion, SuccRegion};
%        true ->
%            {R1, R2} = {PredRegion, SuccRegion}
%    end,
    S2 = #region_state{
        id = now(),
        pred = State#region_state.self,
        succ = State#region_state.succ,
        topological_region = SuccRegion
    },
    Pid2 = spawn(?MODULE, vc_server, [S2]),

    Pred = State#region_state.pred,
    Succ = State#region_state.succ,
    {Interface1, Interface2} = PredRegion#topological_region.interface,
    Pred ! {adjust_outlet, {Interface2, Interface1}},
    {Outerface1, Outerface2} = SuccRegion#topological_region.outerface,
    Succ ! {adjust_inlet, {Outerface2, Outerface1}},

    State#region_state{
        succ = Pid2,
        topological_region = PredRegion
    }.

traverse(State, Flag) ->
    if
        State#region_state.traverse_version < Flag ->
            io:format("id: ~p~n", [State#region_state.id]),
            io:format("    (~p)~n", [State#region_state.topological_region]),
            State#region_state.succ ! {traverse,Flag},
            State#region_state{traverse_version = Flag};
        true ->
            State
    end.


